import number from "@/mount/global/number"
import { GenerateAbility, isInArray, zipPosition } from "@/utils"
import {LabMap} from '@/module/labMap'
import { zip } from "lodash"

/* 任务发布便捷函数 */
export default class PublishMissonExtension extends Room {
    /* 搬运任务的发布函数  爬虫绑定信息、超时时间、源房间、原坐标X、Y、目标房间、目标X、Y、资源类型、数量 */
    public Public_Carry(creepData:BindData,delayTick:number,sR:string,sX:number,sY:number,tR:string,tX:number,tY:number,rType?:ResourceConstant,num?:number):MissionModel{
        var thisTask:MissionModel = 
            {
                name :'物流运输',
                CreepBind:creepData,
                range:'Creep',
                delayTick:delayTick,
                cooldownTick:1,
                data:{
                    sourceRoom:sR,
                    sourcePosX:sX,
                    sourcePosY:sY,
                    targetRoom:tR,
                    targetPosX:tX,
                    targetPosY:tY,
                }
            }
        if (rType) thisTask.data.rType = rType
        if (num) thisTask.data.num = num
        return thisTask
    }

    /* link传送任务发布函数 */
    public Public_Link(structure:string[],disStructure:string,level:number,delayTick?:number):MissionModel{
        var thisTask:MissionModel = {
            name:'链传送能',
            range:'Structure',
            delayTick:20,
            structure:structure,
            level:level,
            data:{
                disStructure:disStructure
            }
        }
        if (delayTick) thisTask.delayTick = delayTick
        return thisTask
    }

    /* 资源传送任务发布函数 */
    public Public_Send(disRoom:string,rType:ResourceConstant,num:number):MissionModel{
        if (!this.memory.StructureIdData.terminalID) return null
        var terminal = Game.getObjectById(this.memory.StructureIdData.terminalID) as StructureTerminal
        if (!terminal)
        {
            delete this.memory.StructureIdData.terminalID
            return null
        }
        var thisTask:MissionModel = {
            name:'资源传送',
            range:'Structure',
            delayTick:5000,
            structure:[terminal.id],
            level:5,
            data:{
                disRoom:disRoom,
                rType:rType,
                num:num
            }
        }
        return thisTask
    }

    /* 任务lab绑定数据生成便捷函数 */
    public Bind_Lab(rTypes:ResourceConstant[]):MissonLabBind | null{
        var result:MissonLabBind = {}
        var tempList = []
        LoopA:
        for (var i of rTypes)
        {
            /* 计算是否已经存在相关lab */
            for (var occ_lab_id in this.memory.RoomLabBind)
            {
                if (this.memory.RoomLabBind[occ_lab_id].rType == i && !this.memory.RoomLabBind[occ_lab_id].occ)
                {
                    result[occ_lab_id] = i
                    continue LoopA
                }
            }
            LoopB:
            for (var all_lab_id of this.memory.StructureIdData.labs)
            {
                var occ_lab = Object.keys(this.memory.RoomLabBind)
                if (!isInArray(occ_lab,all_lab_id) && !isInArray(tempList,all_lab_id))
                {
                    var thisLab = Game.getObjectById(all_lab_id) as StructureLab
                    if (!thisLab)
                    {
                        var index = this.memory.StructureIdData.labs.indexOf(all_lab_id)
                        this.memory.StructureIdData.labs.splice(index,1)
                        continue LoopB
                    }
                    if (thisLab.store)
                    {
                        if (Object.keys(thisLab.store).length <= 1)
                        {
                            result[all_lab_id] = i
                            tempList.push(all_lab_id)
                            continue LoopA
                        }
                        else if (Object.keys(thisLab.store).length == 1)
                        {
                            if (thisLab.store['energy'] > 0)
                            {
                                result[all_lab_id] = i
                                tempList.push(all_lab_id)
                                continue LoopA
                            }
                            continue LoopB
                        }
                        else if (Object.keys(thisLab.store).length > 1)
                        continue LoopB
                    }
                }
            }
            return null
        }
        return result
    }

    /* 资源合成任务发布函数 */
    public Public_Com(num:number,disResource:ResourceConstant,bindData?:string[]):MissionModel{
        // 检验阶段
        if (!this.memory.StructureIdData.labInspect || Object.keys(this.memory.StructureIdData.labInspect).length < 3) return null
        var raw1 = Game.getObjectById(this.memory.StructureIdData.labInspect.raw1) as StructureLab
        var raw2 = Game.getObjectById(this.memory.StructureIdData.labInspect.raw2) as StructureLab
        if (!raw1) {delete this.memory.StructureIdData.labInspect.raw1;return} 
        if (!raw2) {delete this.memory.StructureIdData.labInspect.raw2;return}
        for (var i of this.memory.StructureIdData.labInspect.com)
        {
            var thisLab = Game.getObjectById(i) as StructureLab
            if (!thisLab)
            {
                var index = this.memory.StructureIdData.labInspect.com.indexOf(i)
                this.memory.StructureIdData.labInspect.com.splice(index,1)
                continue
            }
        }
        var raw1str = LabMap[disResource].raw1
        var raw2str = LabMap[disResource].raw2
        /* 开始进行任务 */
        var thisTask:MissionModel = {
            name:'资源合成',
            range:'Room',
            delayTick:50000,
            processing:true,
            level:10,
            LabBind:{
            },
            data:{
                num:num
            }
        }
        thisTask.LabBind[this.memory.StructureIdData.labInspect.raw1] = raw1str
        thisTask.LabBind[this.memory.StructureIdData.labInspect.raw2] = raw2str
        var BindData = bindData?bindData:this.memory.StructureIdData.labInspect.com
        thisTask.data.comData = BindData
        for (var ii of BindData)
        {
            thisTask.LabBind[ii] = disResource
        }
        thisTask.data.raw1 = raw1str
        thisTask.data.raw2 = raw2str
        return thisTask
    }

    /* 资源购买任务发布函数 */
    public Public_Buy(res:ResourceConstant,num:number,range:number,max?:number):MissionModel{
        if (!this.memory.StructureIdData.terminalID) return null
        var terminal = Game.getObjectById(this.memory.StructureIdData.terminalID) as StructureTerminal
        if (!terminal)
        {
            delete this.memory.StructureIdData.terminalID
            return null
        }
        /* 开始进行任务 */
        var thisTask:MissionModel = {
            name:'资源购买',
            range:'Structure',
            structure:[terminal.id],
            delayTick:200,
            level:10,
            maxTime:8,
            data:{
                rType:res,
                num:num,
                range:range
            }
        }
        thisTask.data.maxPrice = max?max:35
        return thisTask
    }

    /* 控制冲级任务发布函数 */
    public Public_level(CreepNum:number,rType:ResourceConstant,Nolab?:boolean):MissionModel
    {
        if (!this.memory.StructureIdData.storageID || !this.memory.StructureIdData.upgrade_link || !this.memory.StructureIdData.center_link)return null
        var thisTask:MissionModel = {
            name:'控制冲级',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                num:CreepNum
            },
        }
        if (rType){thisTask.data.rType = rType;thisTask.data.boosted = true}
        if (!Nolab)
        {
            var labData = this.Bind_Lab([rType])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        thisTask.data.Nolab = Nolab
        thisTask.CreepBind = {'level':{num:CreepNum,bind:[]}}
        return thisTask
    }

    /* 房间签名任务发布函数 */
    public Public_Sign(CreepNum:number,disRoom:string,shard:shardName,words:string):MissionModel{
        var thisTask:MissionModel = {
            name:'房间签名',
            range:'Creep',
            delayTick:1600,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                words:words
            },
        }
        thisTask.CreepBind = {'scout':{num:CreepNum,bind:[]}}
        return thisTask
    }

    /* 房间援建一体任务发布函数 */
    public Public_BoostBuild(disRoom:string,shard:shardName,buildNum:number,claimNum:number):MissionModel{
        var thisTask:MissionModel = {
            name:'援建一体',
            range:'Creep',
            delayTick:2000,
            level:5,
            data:{
                disRoom:disRoom,
                shard:shard,
            },
        }
        thisTask.CreepBind = {'claim':{num:claimNum,bind:[]},'architect':{num:buildNum,bind:[]}}
        var labData = this.Bind_Lab(['XGHO2','XLHO2','XLH2O','XZHO2','XKH2O'])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }

    /* 协助升级任务发布函数 */
    public Public_HelpUpgrade(disRoom:string,shard:shardName,CreepNum:number):MissionModel{
        var thisTask:MissionModel = {
            name:'协助升级',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                build_help_num:CreepNum
            },
        }
        thisTask.CreepBind = {'upgrade-help':{num:CreepNum,bind:[]}}
        var labData = this.Bind_Lab(['XGH2O','XLHO2','XKH2O','XZHO2',])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }

    /* 后勤协助 */
    public Public_HelpRear(disRoom:string,shard:shardName,CreepNum:number,rType:ResourceConstant,time:number):MissionModel{
        var thisTask:MissionModel = {
            name:'后勤协助',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                time:time,
                rType:rType,
                build_help_num:CreepNum
            },
        }
        thisTask.CreepBind = {'rear-help':{num:CreepNum,bind:[]}}
        var labData = this.Bind_Lab(['XKH2O','XLHO2','XLH2O','XZHO2','XGHO2'])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }

    /* 一体机任务 */
    public Publid_Aio(disRoom:string,shard:shardName,CreepNum:number,time:number,body?:number[]):MissionModel{
        var thisTask:MissionModel = {
            name:'攻防一体',
            range:'Creep',
            delayTick:30000,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                time:time,
                num:CreepNum
            },
        }
        thisTask.CreepBind = {'aio':{num:CreepNum,bind:[]}}
        var labData = this.Bind_Lab(['XKHO2','XLHO2','XZHO2','XGHO2'])
        if (labData === null) return null
        thisTask.LabBind = labData
        if (body && body.length == 3)       // tough ranged_attack heal部件
        {
            var n = 0
            for (var b of body)  n+= b
            if (n < 40)
            {
                var bodyData:BodyPartConstant[] = GenerateAbility(0,0,10,0,body[1],body[2],0,body[0])
                thisTask.data.bodyNum = bodyData
            }
        }
        return thisTask
    }

    /* om杀手任务 */
    public Public_OMKiller(disRoom:string,shard:shardName):MissionModel{
        var thisTask:MissionModel = {
            name:'om杀手',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
            },
        }
        thisTask.CreepBind = {'om-killer':{num:1,bind:[]}}
        thisTask.maxTime = 5
        return thisTask
    }

    /* 双人小队发布函数 */
    public Public_Double(disRoom:string,shard:shardName,CreepNum:number,cType:'dismantle' | 'attack'):MissionModel{
        var thisTask:MissionModel = {
            name:'双人小队',
            range:'Creep',
            delayTick:20000,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                teamType:cType,
                num:CreepNum
            },
        }
        if (cType == 'dismantle')
        {
            thisTask.CreepBind = {'double-dismantle':{num:CreepNum,bind:[]},'double-heal':{num:CreepNum,bind:[]}}
            var labData = this.Bind_Lab(['XZHO2','XZH2O','XGHO2','XLHO2'])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        else
        {
            thisTask.CreepBind = {'double-attack':{num:CreepNum,bind:[]},'double-heal':{num:CreepNum,bind:[]}}
            var labData = this.Bind_Lab(['XUH2O','XZHO2','XGHO2','XLHO2'])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        return thisTask
    }
    
    /* R型四人小队发布函数 即将废弃 */
    public Public_XR(disRoom:string,shard:shardName):MissionModel{
        var thisTask:MissionModel = {
            name:'X-R',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
            },
        }
        thisTask.CreepBind = {'X-R-A':{num:2,bind:[]},'X-R-B':{num:2,bind:[]}}
        var labData = this.Bind_Lab(['XGHO2','XLHO2','XKHO2','XZHO2'])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }

    public Public_squard(disRoom:string,shard:shardName,sType:'X-R'|'X-A'|'X-D'|'X-M'):MissionModel{
        if (this.controller.level < 7) return null
        var thisTask:MissionModel = {
            name:'四人小队',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                sType:sType
            },
        }
        if(sType == 'X-R')
        {
            thisTask.CreepBind = {'X-R-A':{num:2,bind:[]},'X-R-B':{num:2,bind:[]}}
            var labData = this.Bind_Lab(['XGHO2','XLHO2','XKHO2','XZHO2'])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        else if (sType == 'X-A')
        {
            thisTask.CreepBind = {'X-A-A':{num:2,bind:[]},'X-A-B':{num:2,bind:[]}}
            var labData = this.Bind_Lab(['XGHO2','XLHO2','XKHO2','XZHO2','XUH2O'])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        else
        {
            return null
        }
        return thisTask
    }

    /* power采集任务发布函数 */
    public public_PowerHarvest(disRoom:string,x:number,y:number,num:number):MissionModel{
        var thisTask:MissionModel = {
            name:'power采集',
            range:'Creep',
            delayTick:5000,
            level:10,
            data:{
                room:disRoom,
                x:x,
                y:y,
                state:1,
                num:num
            },
        }
        thisTask.CreepBind = {'power-attack':{num:1,bind:[]},'power-heal':{num:1,bind:[]},'power-carry':{num: Math.ceil(num/1600),bind:[]}} 
        var MissonNum = this.MissonNum('Creep','power采集')
        /* 最多同时允许一个power采集任务 */
        if (MissonNum > 1) return null
        thisTask.maxTime = MissonNum + 1
        return thisTask
    }

    /* deposit采集任务发布函数 */
    public public_DepositHarvest(disRoom:string,x:number,y:number,rType:DepositConstant):MissionModel{
        var thisTask:MissionModel = {
            name:'deposit采集',
            range:'Creep',
            delayTick:2000,
            level:10,
            data:{
                room:disRoom,
                x:x,
                y:y,
                state:1,
                rType:rType
            },
        }
        thisTask.CreepBind = {'deposit':{num:1,bind:[]}}
        var MissonNum = this.MissonNum('Creep','deposit采集')
        if (MissonNum > 2) return null
        thisTask.maxTime = MissonNum
        return thisTask
    }

    /* 外矿开采任务发布函数 */
    public public_OutMine(sourceRoom:string,x:number,y:number,disRoom:string):MissionModel{
        var pos = new RoomPosition(x,y,sourceRoom)
        if (!this.memory.StructureIdData.storageID) return null
        if (!pos) return null
        // 检查是否重复
        for (var i of this.memory.Misson['Creep'])
        {
            if (i.name == '外矿开采' && i.data.disRoom == disRoom)
            return null
        }
        var thisTask:MissionModel = {
            name:'外矿开采',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                disRoom:disRoom,
                startpoint:zipPosition(pos)
            },
        }
        thisTask.CreepBind = {'out-claim':{num:1,bind:[]},'out-harvest':{num:0,bind:[]},'out-car':{num:0,bind:[]},'out-defend':{num:0,bind:[]}}
        return thisTask
    }

    public public_repair(Rtype:'global' | 'special' | 'nuker',num:number,boostType:number,vindicate:boolean):MissionModel
    {
        var thisTask:MissionModel = {
            name:'墙体维护',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                RepairType:Rtype,
                num:num,
                boostType:boostType,
                vindicate:vindicate
            },
        }
        thisTask.CreepBind = {'repair':{num:num,bind:[]}}
        if (boostType == 1)
        {
            var labData = this.Bind_Lab(['LH','KH',])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        else if (boostType == 2)
        {
            var labData = this.Bind_Lab(['LH2O','KH2O',])
            if (labData === null) return null
            thisTask.LabBind = labData

        }
        else if (boostType == 3)
        {
            var labData = this.Bind_Lab(['XLH2O','XKH2O',])
            if (labData === null) return null
            thisTask.LabBind = labData
        }
        thisTask.maxTime = 3
        return thisTask
    }

    /* 主动防御任务发布函数 */
    public public_defend(AttackNum:number,RangeNum:number,DoubleNum:number):MissionModel{
        if (!AttackNum && !RangeNum && !DoubleNum) return null
        var thisTask:MissionModel = {
            name:'主动防御',
            range:'Creep',
            delayTick:99999,
            level:10,
            data:{
                
            },
        }
        var comList = ['XZHO2']
        thisTask.CreepBind = {}
        if (AttackNum > 0)
        {
            comList.push('XUH2O')
            thisTask.CreepBind['defend-attack'] = {num:AttackNum,bind:[]}

        }
        if (RangeNum > 0)
        {
            comList.push('XKHO2')
            thisTask.CreepBind['defend-range'] = {num:RangeNum,bind:[]}

        }
        if (DoubleNum > 0)
        {
            comList.push('XLHO2')
            if (!isInArray(comList,'XUH2O')) comList.push('XUH2O')
            comList.push('XGHO2')
            thisTask.CreepBind['double-attack'] = {num:RangeNum,bind:[]}
            thisTask.CreepBind['double-heal'] = {num:RangeNum,bind:[]}
        }
        var labData = this.Bind_Lab(comList as ResourceConstant[])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }

    /* 黄球拆迁任务发布函数 */
    public Public_Dismantle(disRoom:string,shard:shardName,CreepNum:number,time:number):MissionModel{
        var thisTask:MissionModel = {
            name:'黄球拆迁',
            range:'Creep',
            delayTick:30000,
            level:10,
            data:{
                disRoom:disRoom,
                shard:shard,
                time:time,
                num:CreepNum
            },
        }
        thisTask.CreepBind = {'dismantle':{num:CreepNum,bind:[]}}
        var labData = this.Bind_Lab(['XZH2O','XZHO2'])
        if (labData === null) return null
        thisTask.LabBind = labData
        return thisTask
    }
    
}